package com.dhcc.DRGsHosp.infra.util;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Map;

import com.dhcc.DRGsHosp.infra.util.eval.Expression;

/**
 * @title		:Arith.java
 * @description	:浮点数运算
 * @author		:lileizheng
 * @date		:2015年7月17日
 * @version     :1.0
 * @copyright   :DHCC 2013-2014
 */
public class Arith{
    //默认除法运算精度
    private static final int DEF_DIV_SCALE = 10;
    //这个类不能实例化
    private Arith(){
    }
 
    /**
     * 提供精确的加法运算。
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(double v1,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }
    /**
     * 提供精确的减法运算。
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(double v1,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    } 
    
    /**
     * 提供精确的乘法运算。
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mul(double v1,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }
 
    /**
     * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到
     * 小数点以后10位，以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static double div(double v1,double v2){
        return div(v1,v2,DEF_DIV_SCALE);
    }
 
    /**
     * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指
     * 定精度，以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1,double v2,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                "The scale must be a positive integer or zero");
        }
        if(v2==0){
        	return 0;
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }
    
    /**
     * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指
     * 定精度，以后的数字直接舍去。
     * @param v1 被除数
     * @param v2 除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div_d(double v1,double v2,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                "The scale must be a positive integer or zero");
        }
        if(v2==0){
        	return 0;
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2,scale,BigDecimal.ROUND_DOWN).doubleValue();
    }
 
    /**
     * 提供精确的小数位四舍五入处理。
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }
    /**
     * 提供精确的小数位处理。
     * @param v 直接舍入的数字
     * @param scale 小数点后保留几位
     * @return 舍入结果
     */
    public static double round_u(double v,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one,scale,BigDecimal.ROUND_UP).doubleValue();
    }
    
    /**
     * 提供精确的小数位处理。
     * @param v 直接舍去的数字
     * @param scale 小数点后保留几位
     * @return 舍入结果
     */
    public static double round_d(double v,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one,scale,BigDecimal.ROUND_DOWN).doubleValue();
    }
    
    /**
     * mrOutDateSql.  
     * Description:首页查询时间方法
     * author LiuHongjun
     * @param dateFrom 开始时间
     * @param dateTo结束时间
     * @param alias 表别名
     * @param tyle  1.普通类型 2或其他：setParameters传参
     * @return 返回sql
     * Date:2017年2月20日上午9:25:55
     * 修改日期格式为orcale,屏蔽掉的事mysql
     */
    public static String mrAROutDateSql(String  dateFrom,String  dateTo,String alias){
    	String str="";
//    	if(type==1){
//    		   str=" AND "+alias+".OUT_DATE  BETWEEN STR_TO_DATE('"+dateFrom+"','%Y-%m-%d %H:%i:%s') AND STR_TO_DATE('"+dateTo+"','%Y-%m-%d %H:%i:%s')";
//    	}else{
// 		     str=" AND "+alias+".OUT_DATE  BETWEEN STR_TO_DATE(:"+dateFrom+",'%Y-%m-%d %H:%i:%s') AND STR_TO_DATE(:"+dateTo+",'%Y-%m-%d %H:%i:%s')";
//    	}
 		str=" AND to_char( "+alias+".P00290000 ,'yyyy-mm-dd')  BETWEEN '"+dateFrom+"' and '"+dateTo+"' ";
        return str;
    }
    /**
     * Description ：老版分析报告时间函数
     * date: 2017年11月9日 下午12:28:05  
     * @author ShaozhiYuan
     * @version V1.0 DHC
     */
    public static String mrOutDateSql(String  dateFrom,String  dateTo,String alias,int type){
    	String str="";
//    	if(type==1){
//    		   str=" AND "+alias+".OUT_DATE  BETWEEN STR_TO_DATE('"+dateFrom+"','%Y-%m-%d %H:%i:%s') AND STR_TO_DATE('"+dateTo+"','%Y-%m-%d %H:%i:%s')";
//    	}else{
// 		     str=" AND "+alias+".OUT_DATE  BETWEEN STR_TO_DATE(:"+dateFrom+",'%Y-%m-%d %H:%i:%s') AND STR_TO_DATE(:"+dateTo+",'%Y-%m-%d %H:%i:%s')";
//    	}
    	if(type==1){
 		   str=" AND "+alias+".P00290000  BETWEEN TO_DATE('"+dateFrom+"','yyyy-mm-dd hh24:mi:ss') AND TO_DATE('"+dateTo+"','yyyy-mm-dd hh24:mi:ss')";
	 	}else{
		   str=" AND "+alias+".P00290000  BETWEEN TO_DATE(:"+dateFrom+",'yyyy-mm-dd hh24:mi:ss') AND TO_DATE(:"+dateTo+",'yyyy-mm-dd hh24:mi:ss')";
	 	}
        return str;
    }
    /**
     * 分析报告中过滤临床专业覆盖病组
     * @param drgVersion
     * @param specCode
     * @param alias
     * @return
     */
    public static String pdInDpDRGSql(String  drgVersion,String  specCode,String alias){
    	String str="";
    	if("all".equals(specCode)){
    		str=" and "+alias+".Pardrg_Code in ( select  distinct t.pardrg_code from DRGS.T_DEPARTMENTDRG t  LEFT JOIN DRGS.T_CLISPEC CLI ON CLI.SPEC_CODE = t.parspec_code   where t.version='"+drgVersion+"' ) ";
    	}else{
    		str=" and "+alias+".Pardrg_Code in ( select  distinct t.pardrg_code from DRGS.T_DEPARTMENTDRG t  LEFT JOIN DRGS.T_CLISPEC CLI ON CLI.SPEC_CODE = t.parspec_code   where t.version='"+drgVersion+"' and CLI.SPEC_CODE='"+specCode+"' ) ";
    	}
 		
        return str;
    }
    /**
     * 
     * dataFormat.  
     * Description:数字格式化
     * author LiuHongjun
     * @param a
     * @param type 1.("0.00"); 2.("#,###") 3.("#,##0.00")
     * @return 
     * Date:2017年2月24日下午2:45:43
     */
    public static String dataFormat(String a,String type){
    	DecimalFormat df = new DecimalFormat("0.00");//1
		DecimalFormat money = new DecimalFormat("#,###");//2
		DecimalFormat moneydb = new DecimalFormat("#,##0.00");//3
		String mya=(a.trim()==null ||a.trim()==""||a.trim()=="undefined" ||!isNumeric(a.trim()))?"0" :a.trim();
         String m="";
         if("1".equals(type)){
        	m=df.format(Double.valueOf(mya).doubleValue()) ;
         }else if ("2".equals(type)) {
        	 m=money.format(Double.valueOf(mya).intValue()) ;
		}else if ("3".equals(type)) {
			m=moneydb.format(Double.valueOf(mya).doubleValue()) ;
		}
        return m;
    }
    /**
     * isNumeric.  
     * Description:判断是否位数字
     * author LiuHongjun
     * @param str
     * @return 
     * Date:2017年2月24日下午2:48:34
     */
    public static boolean isNumeric(String str){ 
    	 if(str.matches("^(?!(0[0-9]{0,}$))[0-9]{1,}[.]{0,}[0-9]{0,}$")){
    		 return true;  
    	 }else{
    		 return false;
    	 }
    	}
		/**
     * @methodname    :evalExpression
     * @description   :自定义表达式
     * @param         :
     * @author        :lileizheng
     * @return        :
     * @date          :2016年12月16日
     */
    public static double evalExpression(String expression, Map<String, BigDecimal> variables){
    	double r = 0d;
    	try{
    		Expression exp1 = new Expression(expression); 
            BigDecimal result = exp1.eval(variables);    //计算表达式的值  
            r = result.doubleValue();
    	}catch(Exception e){
    		e.printStackTrace();
    	}
        return r;
    }
}